/**
********************************************************************************
@file     unit_test.c
@brief    对文件的简要说明
@details  对文件的详细说明
@author   jcai
@date     2024-09-08 22:48:37
@copyright Copyright &copy; 2024 wy1107412334@163.com All rights reserved
@version  v0.0.10

\n Email:  wy1107412334@163.com
\n Blog:   None
\n Github: https://github.com/wy1107412334
\n Gitee:  https://gitee.com/git.git1107412334.com

********************************************************************************
@note
None.
********************************************************************************
@attention

C语言单元测试框架
================

术语说明:
- FUT: 意思是被测试的函数，是(function under test)的缩写

用法
----

1. 初始化本测试框架: unit_test_init()
2. 注册FUT的测试用例到本测试框架:
  1. 将FUT的测试用例注册到测试库中: unit_test_fut_register()
  2. 将测试库注册到本测试框架中: unit_test_lib_register()
3. 运行注册到本测试框架中的测试用例: unit_test_run()
4. 获取测试用例运行结果: unit_test_result_get()
5. [可选]测试用例运行完成后，退出程序: unit_test_exit()

对于本测试框架的使用，请查看本测试框架的测试代码，这些测试代码位于本项目的
根目录的 test 目录下。

********************************************************************************
@verbatim
@endverbatim
********************************************************************************
@par 修订记录
- jcai, 2024-10-20
  - 数值校验函数输出比较的数值中增加16进制值的输出
  - 修改输出测试用例校验结果的格式
- jcai, 2024-09-21
  - 给校验指针的函数的 act 与 exp 加上修饰符 const
- jcai, 2024-09-21
  - 新增函数 unit_test_failed()
  - 为校验函数增加使用注意事项的注释
- jcai, 2024-09-17
  - 新增函数 unit_test_result_get()
- jcai, 2024-09-14
  - 新增如下类型的API:
    - 校验指针相等与不相等
    - 校验实际值小于预期值
    - 校验实际值小于等于预期值
    - 校验实际值大于预期值
    - 校验实际值大于等于预期值
- jcai, 2024-09-14
  - 新增函数头注释
- jcai, 2024-09-13
  - 修复函数 ut_verify_i8_eq()/ut_verify_u8_eq()/ut_verify_i8_ne()/ut_verify_u8_ne()
  - 上述函数输出的一些校验值，保存到文件中后，导致Windows系统中打开文件时无法
    正确的探测出文件中字符编码，是由于使用格式控制字符 %c 输出的部分值导致的，
    例如大于 0x7F 的值
- jcai, 2024-09-10
  - 修复函数 unit_test_results() 中的错误
  - 修复函数 ut_verify_string_eq()/ut_verify_string_ne() 中的错误
  - 修复函数 ut_verify_buffer_eq()/ut_verify_buffer_ne() 中的错误
- jcai, 2024-09-10
  - 调整校验函数的输出内容与格式
- jcai, 2024-09-10
  - 交换验证结果函数的 exp 与 act 这两个参数的位置
- jcai, 2024-09-08 22:48:37
  - 首次编写

********************************************************************************
*/

/* 头文件导入区 ------------------------------------------------------------- */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "unit_test.h"


/** @defgroup UNIT_TEST UNIT_TEST
@brief unit_test modules
@{
*/



/* 宏定义区 ----------------------------------------------------------------- */

/* 获取结构体成员偏移量与获取结构体首地址 */

#ifndef offsetof
#ifdef __compiler_offsetof
/**
 * 获取结构体成员的偏移量
 *
 * 获得成员 MEMBER 在结构体 TYPE 中的偏移量
 *
 * @param TYPE: 一个结构体名
 * @param MEMBER: TYPE 中的一个成员的名字
 * @return MEMBER 在 TYPE 中的偏移量
 * */
#define offsetof(TYPE, MEMBER)  __compiler_offsetof(TYPE, MEMBER)
#else /* !__compiler_offsetof */
/**
 * 获取结构体成员的偏移量
 *
 * 获得成员 MEMBER 在结构体 TYPE 中的偏移量
 *
 * @param TYPE: 一个结构体名
 * @param MEMBER: 结构体 TYPE 中的一个成员的名字
 * @return 成员 MEMBER 在结构体 TYPE 中的偏移量
 * */
#define offsetof(TYPE, MEMBER)  ((unsigned long)&((TYPE *)0)->MEMBER)
#endif /* __compiler_offsetof */
#endif /* !offsetof */

/**
 * 获取结构体首地址
 *
 * 结构体 type 的成员 member 的地址为 ptr， 获取结构体 type 的首地址。
 *
 * @param ptr: 内存地址，是结构体 type 的成员 member 的地址
 * @param type: 结构体类型名
 * @param member: 结构体 type 中的一个成员的名字
 * @return 结构体 type 的首地址
 * @note ptr 需要真的是 type 中成员 member 的地址，否则返回的地址按照 type
 * 的首地址来使用可能会出现无法预料的后果
 * */
#define ut_container_of(ptr, type, member) ({               \
            void *__mptr = (void *)(ptr);                   \
                ((type *)(__mptr - offsetof(type, member))); })


#define UT_FUT_SETUP_FAIL               (1U << 0)
#define UT_FUT_CASE_FAIL                (1U << 1)
#define UT_FUT_IS_FAILED_MASK           (UT_FUT_SETUP_FAIL | UT_FUT_CASE_FAIL)



/* 数据类型声明区 ----------------------------------------------------------- */

typedef struct
{
    UT_SL_LIST  list;           /*!< 保存所有测试库的链表 */
    ut_case_t * pCase;          /*!< 指向当前正在运行的测试用例 */
    uint32_t    caseTotalNum;   /*!< 所有的测试用例的数量 */
    bool        isSuccess;      /*!< 所有的测试用例的测试结果 */
} ut_verify_t;






/* 变量定义区 --------------------------------------------------------------- */


static ut_verify_t ut;








/* 函数定义区 --------------------------------------------------------------- */

/**
********************************************************************************
@brief    计算测试用例的总数
@details
计算注册到测试框架中的所有测试用例的数量。
@param    none
@retval  none
@note    none
*/
static void unit_test_cases_total(void)
{
    uint32_t count = 0;

    UT_SL_FOREACH(plib, &ut.list)
    {
        ut_lib_t * pLib = ut_container_of(plib, ut_lib_t, node);

        // 遍历 fut
        UT_SL_FOREACH(pfut, &pLib->futList)
        {
            ut_cases_info_t * pFut = ut_container_of(pfut, ut_cases_info_t, node);

            count += pFut->caseNum;
        }
    }

    ut.caseTotalNum = count;
}

/**
********************************************************************************
@brief    输出测试结果
@details
输出测试框架运行的所有测试用例的结果:
- 输出运行失败的FUT
- 输出运行失败的数量
- 输出最终运行结果
@param    none
@retval  none
@note    none
*/
static void unit_test_results(void)
{
    const char * resstr = "PASSED";
    uint32_t failedCount = 0;
    bool isSuccess = true;

    if (ut.isSuccess)
    {
        goto end;
    }

    printf("\n\n\n\n********************************************************************************\n");
    printf("FUT that failed to run:\n");

    // 遍历库
    UT_SL_FOREACH(plib, &ut.list)
    {
        ut_lib_t * pLib = ut_container_of(plib, ut_lib_t, node);

        // 遍历测试失败的 fut
        UT_SL_FOREACH(pfut, &pLib->failedList)
        {
            ut_cases_info_t * pFut = ut_container_of(pfut, ut_cases_info_t, failedNode);

            printf("- %s\n", pFut->futName);
            isSuccess = false;


            // 遍历并执行FUT的case
            for (uint32_t i = 0; i < pFut->caseNum; i++)
            {
                ut_case_t * pCase = pFut->cases + i;

                if (!pCase->isSuccess)  failedCount++;
            }
        }   /* 遍历 FUT 结束 */
    }   /* 遍历测试库 结束 */


    printf("\nTotal Test Case Num: %u, Run Failed Num: %u\n",
            ut.caseTotalNum, failedCount);


end:
    if (!isSuccess) resstr = "FAILED";
    printf("\n\n");
    printf("******************** Test Case Result: %s **********************************\n",
           resstr);
}





/**
********************************************************************************
@brief    初始化测试框架
@details  初始化测试框架
@param    none
@retval  none
@note    none
*/
void unit_test_init(void)
{
    ut_sllist_static_init(&ut.list);
    ut.caseTotalNum = 0;
    ut.isSuccess = true;
}

/**
********************************************************************************
@brief    注册待测试的FUT
@details
注册待测试的FUT fut 到测试库 lib 中。
@param[in] lib: 指向测试库的指针
@param[in] fut: 指向待测试的FUT
@retval  none
@note
此函数没有进行参数诊断，所以必须由调用者保证参数 lib 与 fut 的合法性
*/
void unit_test_fut_register(ut_lib_t * lib, ut_cases_info_t * fut)
{
    ut_sllist_insert_tail(&lib->futList, &fut->node);
}

/**
********************************************************************************
@brief    注册测试库到测试框架中
@details
注册测试库 lib 到测试框架中。
@param[in] lib: 指向测试库的指针
@retval  none
@note
此函数没有进行参数诊断，所以必须由调用者保证参数 lib 的合法性
*/
void unit_test_lib_register(ut_lib_t * lib)
{
    ut_sllist_insert_tail(&ut.list, &lib->node);
}

/**
********************************************************************************
@brief    运行测试框架
@details
运行注册到测试框架的所有测试用例
@param   none
@retval  none
@note    none
*/
void unit_test_run(void)
{
    const char * resStr = "";
    bool isLibFirst = true;

    // 统计测试用例的总数
    unit_test_cases_total();
    printf("Total Test Case Num: %u\n", ut.caseTotalNum);

    // 遍历库
    UT_SL_FOREACH(plib, &ut.list)
    {
        ut_lib_t * pLib = ut_container_of(plib, ut_lib_t, node);

        if (!isLibFirst) printf("\n\n\n\n");
        else isLibFirst = false;

        printf("********************************************************************************\n");
        printf("Test Library Name: %s\n", pLib->libName);
        printf("Test Source Path: %s\n", pLib->sourcePath);

        // 遍历 fut
        UT_SL_FOREACH(pfut, &pLib->futList)
        {
            ut_cases_info_t * pFut = ut_container_of(pfut, ut_cases_info_t, node);

            printf("\n\n========================================\n");
            printf("FUT Name: %s\n", pFut->futName);
            printf("========================================\n\n");

            // 运行FUT的setup
            if (pFut->futSetup)
            {
                STATUS st = pFut->futSetup();
                if (st != OK)
                {
                    printf("\tSetup execution failed!......\n");

                    pFut->flags |= UT_FUT_SETUP_FAIL;

                    goto futEnd;
                }
            }

            // 遍历并执行FUT的case
            for (uint32_t i = 0; i < pFut->caseNum; i++)
            {
                ut_case_t * pCase = pFut->cases + i;

                pCase->verifiedCount = 0;
                pCase->isSuccess = true;
                ut.pCase = pCase;

                printf("Test Cases Name: %s\n", pCase->caseName);
                printf("========================================\n");

                // 运行FUT测试用例
                pCase->futEntry();


                // 校验用例测试结果
                if (pCase->verifiedCount != pCase->checkCount)
                {
                    pCase->isSuccess = false;
                    printf("\nCheck Verify Count Error: (%u != %u)\n",
                           pCase->verifiedCount, pCase->checkCount);
                }

                resStr = "PASSED";
                if (!pCase->isSuccess)
                {
                    pFut->flags |= UT_FUT_CASE_FAIL;
                    resStr = "FAILED";
                }

                printf("\n\tRun Result: <<<%s>>>\n\n", resStr);
            }

            // 运行FUT的cleanup
            if (pFut->futCleanup)
            {
                pFut->futCleanup();
            }

futEnd:
            resStr = "PASSED";
            // 如果当前FUT有case失败，那么将其添加到失败列表
            if (pFut->flags & UT_FUT_IS_FAILED_MASK)
            {
                ut_sllist_insert_tail(&pLib->failedList, &pFut->failedNode);
                ut.isSuccess = false;
                resStr = "FAILED";
            }

            printf("\n\t<<<%s>>>\n\n", resStr);
        }   /* 遍历 FUT 结束 */
    }   /* 遍历测试库 结束 */


    // 统计结果
    unit_test_results();
}

/**
********************************************************************************
@brief    获取测试用例的运行结果
@details
获取测试用例的运行结果。
@param   none
@retval true 所有测试用例执行成功
@retval false 有测试用例执行失败
@note
需要在函数 unit_test_run() 执行完成后调用；否则本函数的返回值是假的
*/
bool unit_test_result_get(void)
{
    return ut.isSuccess;
}

/**
********************************************************************************
@brief    退出测试框架
@details
调用本函数，将导致程序退出。如果测试框架运行的所有测试用例中由任何一个测试失败，
那么程序的退出码为1；如果所有的测试用例测试成功，程序的退出码为0。
@param   none
@retval  none
@note    none
*/
void unit_test_exit(void)
{
    exit(!ut.isSuccess);
}

/**
********************************************************************************
@brief    校验布尔类型的值相等
@details
- 如果 act 与 exp 的值都为真(true)或假(false)，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
void unit_test_failed(const char * msg)
{
    ut.pCase->isSuccess = false;
    printf("<<<FAILED>>  %s: '%s'\n", ut.pCase->caseName, msg);
}

/**
********************************************************************************
@brief    校验布尔类型的值相等
@details
- 如果 act 与 exp 的值都为真(true)或假(false)，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_bool_eq(bool act, bool exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    const char * str = "false";
    if (exp) str = "true";
    printf("\tExpected: %s\n", str);

    str = "false";
    if (act) str = "true";
    printf("\tActual:   %s\t", str);

    bool res = (exp == act);
    str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int8_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i8_eq(int8_t act, int8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    if (isprint(exp))
    {
        printf("\tExpected: '%c'\n", exp);
    }
    else
    {
        printf("\tExpected: 0x%02X\n", exp & 0xFF);
    }
    if (isprint(exp))
    {
        printf("\tActual:   '%c'\t", act);
    }
    else
    {
        printf("\tActual:   0x%02X\t", act & 0xFF);
    }

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint8_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u8_eq(uint8_t act, uint8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: 0x%02X\n", exp & 0xFF);
    printf("\tActual:   0x%02X\t", act & 0xFF);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int16_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i16_eq(int16_t act, int16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hd (0x%04X)\n", exp, exp);
    printf("\tActual:   %hd (0x%04X)\t", act, act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint16_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u16_eq(uint16_t act, uint16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hu (0x%04X)\n", exp, exp);
    printf("\tActual:   %hu (0x%04X)\t", act, act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int32_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i32_eq(int32_t act, int32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %d (0x%08X)\n", exp, exp);
    printf("\tActual:   %d (0x%08X)\t", act, act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint32_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u32_eq(uint32_t act, uint32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %u (0x%08X)\n", exp, exp);
    printf("\tActual:   %u (0x%08X)\t", act, act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int64_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i64_eq(int64_t act, int64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %ld (0x%016lX)\n", exp, exp);
    printf("\tActual:   %ld (0x%016lX)\t", act, act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint64_t类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u64_eq(uint64_t act, uint64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lu (0x%016lX)\n", exp, exp);
    printf("\tActual:   %lu (0x%016lX)\t", act, act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验float类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f32_eq(float act, float exp, const char * msg)
{
    uint32_t *pAct = (uint32_t *) &act;
    uint32_t *pExp = (uint32_t *) &exp;
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: %f (0x%08X)\n", exp, *pExp);
    printf("\tActual:   %f (0x%08X)\t", act, *pAct);

    bool res = (*pExp == *pAct);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验double类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f64_eq(double act, double exp, const char * msg)
{
    uint64_t *pAct = (uint64_t *) &act;
    uint64_t *pExp = (uint64_t *) &exp;
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: %lf (0x%08lX)\n", exp, *pExp);
    printf("\tActual:   %lf (0x%08lX)\t", act, *pAct);

    bool res = (*pExp == *pAct);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验字符串相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- 字符串相等的情况:
  - act 与 exp 的字符串内容一样
  - exp 的字符串结束符位置，act 相应位置也是字符串结束符

- 参数 act, exp 与 msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_string_eq(const char * act, const char * exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: \"%s\"\n", exp);
    printf("\tActual:   \"%s\"\t", act);

    const char * str = "OK";
    bool res = true;
    uint32_t explen = strlen(exp);
    if (strncmp(exp, act, explen + 1))
    {
notEqual:
        str = "FAIL";
        ut.pCase->isSuccess = res = false;
    }
    else if (*(exp + explen) != '\0')
        goto notEqual;
    printf("%s\n", str);

    if (!ut.pCase->isSuccess)
    {
        uint32_t actlen = strlen(act);
        uint32_t minlen = (actlen <= explen) ? actlen : explen;
        uint32_t maxlen = (actlen >= explen) ? actlen : explen;
        for (uint32_t i = 0; i < maxlen + 1; i++)
        {
            if (i <= minlen)
            {
                if (*(exp + i) == *(act + i))   continue;

                printf("\tExpectation[%u](%c) != Actual[%u](%c)\n",
                       i, *(exp + i), i, *(act + i));
            }
            else if (minlen == actlen)
            {
                printf("\tExpectation[%u](%c) != Actual[%u]()\n",
                       i, *(exp + i), i);
            }
            else // if (minlen == explen)
            {
                printf("\tExpectation[%u]() != Actual[%u](%c)\n",
                       i, i, *(act + i));
            }
        }
    }

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验缓冲区的内容相等
@details
- 如果 act 与 exp 指向的缓冲区中 explen 字节都相等，那么校验成功。
- 如果 act 与 exp 指向的缓冲区中 explen 字节中有任意值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- 参数 act, exp 与 msg 不能为 NULL
- act 与 exp 指向的缓冲区的长度至少为 explen
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_buffer_eq(void * act, void * exp, uint32_t explen, const char * msg)
{
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: ");
    for (uint32_t i = 0; i < explen; i++)
    {
        printf("%02X ", *((char *)exp + i) & 0xff);
    }
    printf("\n");

    printf("\tActual:   ");
    for (uint32_t i = 0; i < explen; i++)
    {
        printf("%02X ", *((char *)act + i) & 0xff);
    }
    printf("\t");

    const char * str = "OK";
    bool res = true;
    if (memcmp(exp, act, explen))
    {
        str = "FAIL";
        ut.pCase->isSuccess = res = false;
    }
    printf("%s\n", str);

    if (!ut.pCase->isSuccess)
    {
        for (uint32_t i = 0; i < explen; i++)
        {
            if (*((char *)exp + i) == *((char *)act + i))   continue;

            printf("\tExpectation[%u](%#02x) != Actual[%u](%#02x)\n",
                   i, *((char *)exp + i) & 0xff,
                   i, *((char *)act + i) & 0xff);
        }
    }

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验指针类型的值相等
@details
- 如果 act 与 exp 的值都相等，那么校验成功。
- 如果 act 与 exp 的值不相等，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_ptr_eq(const void * act, const void * exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: %p\n", exp);
    printf("\tActual:   %p\t", act);

    bool res = (exp == act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}


/**
********************************************************************************
@brief    校验布尔类型的值不相等
@details
- 如果 act 与 exp 的值都为真(true)或假(false)，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_bool_ne(bool act, bool exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    const char * str = "false";
    if (exp) str = "true";
    printf("\tExpected: %s\n", str);

    str = "false";
    if (act) str = "true";
    printf("\tActual:   %s\t", str);

    bool res = (exp != act);
    str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int8_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i8_ne(int8_t act, int8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    if (isprint(exp))
    {
        printf("\tExpected: '%c'\n", exp);
    }
    else
    {
        printf("\tExpected: 0x%02X\n", exp & 0xFF);
    }
    if (isprint(exp))
    {
        printf("\tActual:   '%c'\t", act);
    }
    else
    {
        printf("\tActual:   0x%02X\t", act & 0xFF);
    }

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint8_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u8_ne(uint8_t act, uint8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: 0x%02X\n", exp & 0xFF);
    printf("\tActual:   0x%02X\t", act & 0xFF);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int16_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i16_ne(int16_t act, int16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hd (0x%04X)\n", exp, exp);
    printf("\tActual:   %hd (0x%04X)\t", act, act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint16_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u16_ne(uint16_t act, uint16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hu (0x%04X)\n", exp, exp);
    printf("\tActual:   %hu (0x%04X)\t", act, act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int32_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i32_ne(int32_t act, int32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %d (0x%08X)\n", exp, exp);
    printf("\tActual:   %d (0x%08X)\t", act, act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint32_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u32_ne(uint32_t act, uint32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %u (0x%08X)\n", exp, exp);
    printf("\tActual:   %u (0x%08X)\t", act, act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int64_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i64_ne(int64_t act, int64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %ld (0x%016lX)\n", exp, exp);
    printf("\tActual:   %ld (0x%016lX)\t", act, act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint64_t类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u64_ne(uint64_t act, uint64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lu (0x%016lX)\n", exp, exp);
    printf("\tActual:   %lu (0x%016lX)\t", act, act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验float类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f32_ne(float act, float exp, const char * msg)
{
    uint32_t *pAct = (uint32_t *) &act;
    uint32_t *pExp = (uint32_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %f (0x%08X)\n", exp, *pExp);
    printf("\tActual:   %f (0x%08X)\t", act, *pAct);

    bool res = (*pExp != *pAct);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验double类型的值不相等
@details
- 如果 act 与 exp 的值相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f64_ne(double act, double exp, const char * msg)
{
    uint64_t *pAct = (uint64_t *) &act;
    uint64_t *pExp = (uint64_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lf (0x%016lX)\n", exp, *pExp);
    printf("\tActual:   %lf (0x%016lX)\t", act, *pAct);

    bool res = (*pExp != *pAct);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验字符串不相等
@details
- 如果 act 与 exp 指向的字符串都相等，那么校验失败。
- 如果 act 与 exp 指向的字符串有任意字符不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- 字符串相等的情况:
  - act 与 exp 的字符串内容一样
  - exp 的字符串结束符位置，act 相应位置也是字符串结束符

- 参数 act, exp 与 msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_string_ne(const char * act, const char * exp, uint32_t explen, const char * msg)
{
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: \"%s\"\n", exp);
    printf("\tActual:   \"%s\"\t", act);

    const char * str = "OK";
    bool res = true;
    if (!strncmp(exp, act, explen + 1))
    {
        str = "FAIL";
        ut.pCase->isSuccess = res = false;
    }
    printf("%s\n", str);

    if (!ut.pCase->isSuccess)
    {
        uint32_t actlen = strlen(act);
        uint32_t minlen = (actlen <= explen) ? actlen : explen;
        for (uint32_t i = 0; i < minlen + 1; i++)
        {
            if (i <= minlen)
            {
                if (*(exp + i) != *(act + i))   continue;

                printf("\tExpectation[%u](%c) == Actual[%u](%c)\n",
                       i, *(exp + i), i, *(act + i));
            }
        }
    }

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验缓冲区的内容不相等
@details
- 如果 act 与 exp 指向的缓冲区中 explen 字节都相等，那么校验失败。
- 如果 act 与 exp 指向的缓冲区中 explen 字节中有任意值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- 参数 act, exp 与 msg 不能为 NULL
- act 与 exp 指向的缓冲区的长度至少为 explen
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_buffer_ne(void * act, void * exp, uint32_t explen, const char * msg)
{
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: ");
    for (uint32_t i = 0; i < explen; i++)
    {
        printf("%02X ", *((char *)exp + i) & 0xff);
    }
    printf("\n");

    printf("\tActual:   ");
    for (uint32_t i = 0; i < explen; i++)
    {
        printf("%02X ", *((char *)act + i) & 0xff);
    }
    printf("\t");

    const char * str = "OK";
    bool res = true;
    if (!memcmp(exp, act, explen))
    {
        str = "FAIL";
        ut.pCase->isSuccess = res = false;
    }
    printf("%s\n", str);

    if (!ut.pCase->isSuccess)
    {
        for (uint32_t i = 0; i < explen; i++)
        {
            if (*((char *)exp + i) != *((char *)act + i))   continue;

            printf("\tExpectation[%u](0x%02X) == Actual[%u](0x%02X)\n",
                   i, *((char *)exp + i) & 0xff,
                   i, *((char *)act + i) & 0xff);
        }
    }

    ut.pCase->verifiedCount++;

    return res;
}
/**
********************************************************************************
@brief    校验指针类型的值不相等
@details
- 如果 act 与 exp 的值都相等，那么校验失败。
- 如果 act 与 exp 的值不相等，那么校验成功。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_ptr_ne(const void * act, const void * exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);
    
    printf("\tExpected: %p\n", exp);
    printf("\tActual:   %p\t", act);

    bool res = (exp != act);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}



/**
********************************************************************************
@brief    校验int8_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i8_lt(int8_t act, int8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    if (isprint(exp))
    {
        printf("\tExpected: '%c'\n", exp);
    }
    else
    {
        printf("\tExpected: 0x%02X\n", exp & 0xFF);
    }
    if (isprint(exp))
    {
        printf("\tActual:   '%c'\t", act);
    }
    else
    {
        printf("\tActual:   0x%02X\t", act & 0xFF);
    }

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint8_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u8_lt(uint8_t act, uint8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: 0x%02X\n", exp & 0xFF);
    printf("\tActual:   0x%02X\t", act & 0xFF);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int16_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i16_lt(int16_t act, int16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hd (0x%04X)\n", exp, exp);
    printf("\tActual:   %hd (0x%04X)\t", act, act);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint16_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u16_lt(uint16_t act, uint16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hu (0x%04X)\n", exp, exp);
    printf("\tActual:   %hu (0x%04X)\t", act, act);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int32_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i32_lt(int32_t act, int32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %d (0x%08X)\n", exp, exp);
    printf("\tActual:   %d (0x%08X)\t", act, act);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint32_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u32_lt(uint32_t act, uint32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %u (0x%08X)\n", exp, exp);
    printf("\tActual:   %u (0x%08X)\t", act, act);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int64_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i64_lt(int64_t act, int64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %ld (0x%016lX)\n", exp, exp);
    printf("\tActual:   %ld (0x%016lX)\t", act, act);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint64_t类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u64_lt(uint64_t act, uint64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lu (0x%016lX)\n", exp, exp);
    printf("\tActual:   %lu (0x%016lX)\t", act, act);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验float类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f32_lt(float act, float exp, const char * msg)
{
    uint32_t *pAct = (uint32_t *) &act;
    uint32_t *pExp = (uint32_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %f (0x%08X)\n", exp, *pExp);
    printf("\tActual:   %f (0x%08X)\t", act, *pAct);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验double类型的实际值小于预期值
@details
- 如果 act 小于 exp ，那么校验成功。
- 如果 act 大于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f64_lt(double act, double exp, const char * msg)
{
    uint64_t *pAct = (uint64_t *) &act;
    uint64_t *pExp = (uint64_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lf (0x%016lX)\n", exp, *pExp);
    printf("\tActual:   %lf (0x%016lX)\t", act, *pAct);

    bool res = (act < exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}


/**
********************************************************************************
@brief    校验int8_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i8_le(int8_t act, int8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    if (isprint(exp))
    {
        printf("\tExpected: '%c'\n", exp);
    }
    else
    {
        printf("\tExpected: 0x%02X\n", exp & 0xFF);
    }
    if (isprint(exp))
    {
        printf("\tActual:   '%c'\t", act);
    }
    else
    {
        printf("\tActual:   0x%02X\t", act & 0xFF);
    }

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint8_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u8_le(uint8_t act, uint8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: 0x%02X\n", exp & 0xFF);
    printf("\tActual:   0x%02X\t", act & 0xFF);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int16_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i16_le(int16_t act, int16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hd (0x%04X)\n", exp, exp);
    printf("\tActual:   %hd (0x%04X)\t", act, act);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint16_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u16_le(uint16_t act, uint16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hu (0x%04X)\n", exp, exp);
    printf("\tActual:   %hu (0x%04X)\t", act, act);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int32_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i32_le(int32_t act, int32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %d (0x%08X)\n", exp, exp);
    printf("\tActual:   %d (0x%08X)\t", act, act);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint32_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u32_le(uint32_t act, uint32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %u (0x%08X)\n", exp, exp);
    printf("\tActual:   %u (0x%08X)\t", act, act);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int64_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i64_le(int64_t act, int64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %ld (0x%016lX)\n", exp, exp);
    printf("\tActual:   %ld (0x%016lX)\t", act, act);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint64_t类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u64_le(uint64_t act, uint64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lu (0x%016lX)\n", exp, exp);
    printf("\tActual:   %lu (0x%016lX)\t", act, act);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验float类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f32_le(float act, float exp, const char * msg)
{
    uint32_t *pAct = (uint32_t *) &act;
    uint32_t *pExp = (uint32_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %f (0x%08X)\n", exp, *pExp);
    printf("\tActual:   %f (0x%08X)\t", act, *pAct);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验double类型的实际值小于等于预期值
@details
- 如果 act 小于等于 exp ，那么校验成功。
- 如果 act 大于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f64_le(double act, double exp, const char * msg)
{
    uint64_t *pAct = (uint64_t *) &act;
    uint64_t *pExp = (uint64_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lf (0x%016lX)\n", exp, *pExp);
    printf("\tActual:   %lf (0x%016lX)\t", act, *pAct);

    bool res = (act <= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}


/**
********************************************************************************
@brief    校验int8_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i8_gt(int8_t act, int8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    if (isprint(exp))
    {
        printf("\tExpected: '%c'\n", exp);
    }
    else
    {
        printf("\tExpected: 0x%02X\n", exp & 0xFF);
    }
    if (isprint(exp))
    {
        printf("\tActual:   '%c'\t", act);
    }
    else
    {
        printf("\tActual:   0x%02X\t", act & 0xFF);
    }

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint8_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u8_gt(uint8_t act, uint8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: 0x%02X\n", exp & 0xFF);
    printf("\tActual:   0x%02X\t", act & 0xFF);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int16_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i16_gt(int16_t act, int16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hd (0x%04X)\n", exp, exp);
    printf("\tActual:   %hd (0x%04X)\t", act, act);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint16_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u16_gt(uint16_t act, uint16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hu (0x%04X)\n", exp, exp);
    printf("\tActual:   %hu (0x%04X)\t", act, act);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int32_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i32_gt(int32_t act, int32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %d (0x%08X)\n", exp, exp);
    printf("\tActual:   %d (0x%08X)\t", act, act);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint32_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u32_gt(uint32_t act, uint32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %u (0x%08X)\n", exp, exp);
    printf("\tActual:   %u (0x%08X)\t", act, act);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int64_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i64_gt(int64_t act, int64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %ld (0x%016lX)\n", exp, exp);
    printf("\tActual:   %ld (0x%016lX)\t", act, act);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint64_t类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u64_gt(uint64_t act, uint64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lu (0x%016lX)\n", exp, exp);
    printf("\tActual:   %lu (0x%016lX)\t", act, act);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验float类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f32_gt(float act, float exp, const char * msg)
{
    uint32_t *pAct = (uint32_t *) &act;
    uint32_t *pExp = (uint32_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %f (0x%08X)\n", exp, *pExp);
    printf("\tActual:   %f (0x%08X)\t", act, *pAct);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验double类型的实际值大于预期值
@details
- 如果 act 大于 exp ，那么校验成功。
- 如果 act 小于等于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f64_gt(double act, double exp, const char * msg)
{
    uint64_t *pAct = (uint64_t *) &act;
    uint64_t *pExp = (uint64_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lf (0x%016lX)\n", exp, *pExp);
    printf("\tActual:   %lf (0x%016lX)\t", act, *pAct);

    bool res = (act > exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}


/**
********************************************************************************
@brief    校验int8_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i8_ge(int8_t act, int8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    if (isprint(exp))
    {
        printf("\tExpected: '%c'\n", exp);
    }
    else
    {
        printf("\tExpected: 0x%02X\n", exp & 0xFF);
    }
    if (isprint(exp))
    {
        printf("\tActual:   '%c'\t", act);
    }
    else
    {
        printf("\tActual:   0x%02X\t", act & 0xFF);
    }

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint8_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u8_ge(uint8_t act, uint8_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: 0x%02X\n", exp & 0xFF);
    printf("\tActual:   0x%02X\t", act & 0xFF);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int16_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i16_ge(int16_t act, int16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hd (0x%04X)\n", exp, exp);
    printf("\tActual:   %hd (0x%04X)\t", act, act);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint16_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u16_ge(uint16_t act, uint16_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %hu (0x%04X)\n", exp, exp);
    printf("\tActual:   %hu (0x%04X)\t", act, act);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int32_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i32_ge(int32_t act, int32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %d (0x%08X)\n", exp, exp);
    printf("\tActual:   %d (0x%08X)\t", act, act);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint32_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u32_ge(uint32_t act, uint32_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %u (0x%08X)\n", exp, exp);
    printf("\tActual:   %u (0x%08X)\t", act, act);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验int64_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_i64_ge(int64_t act, int64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %ld (0x%016lX)\n", exp, exp);
    printf("\tActual:   %ld (0x%016lX)\t", act, act);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验uint64_t类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_u64_ge(uint64_t act, uint64_t exp, const char * msg)
{
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %lu (0x%016lX)\n", exp, exp);
    printf("\tActual:   %lu (0x%016lX)\t", act, act);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验float类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f32_ge(float act, float exp, const char * msg)
{
    uint32_t *pAct = (uint32_t *) &act;
    uint32_t *pExp = (uint32_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %f (0x%08X)\n", exp, *pExp);
    printf("\tActual:   %f (0x%08X)\t", act, *pAct);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}

/**
********************************************************************************
@brief    校验double类型的实际值大于等于预期值
@details
- 如果 act 大于等于 exp ，那么校验成功。
- 如果 act 小于 exp ，那么校验失败。
@param[in] act: 实际值
@param[in] exp: 预期值
@param[in] msg: 指向一个字符串，描述了本次校验了什么的字符串
@retval true 校验成功
@retval false 校验失败
@note
- msg 不能为 NULL
- 此函数只能在测试用例中调用，不能在 FUT 的setup/cleanup函数及其它地方调用
*/
bool ut_verify_f64_ge(double act, double exp, const char * msg)
{
    uint64_t *pAct = (uint64_t *) &act;
    uint64_t *pExp = (uint64_t *) &exp;
    printf("Verify message: '%s':\n", msg);

    printf("\tExpected: %f (0x%016lX)\n", exp, *pExp);
    printf("\tActual:   %f (0x%016lX)\t", act, *pAct);

    bool res = (act >= exp);
    const char * str = "FAIL";
    if (res)    str = "OK";
    else ut.pCase->isSuccess = res;
    printf("%s\n", str);

    ut.pCase->verifiedCount++;

    return res;
}




/** defgroup UNIT_TEST
@}
*/


/*********************************** END OF FILE ******************************/
